import { onMounted, onBeforeUnmount, ref, h, type Component, type Ref, markRaw } from "vue";
import { Graph, Addon, type Node, type Cell } from "@antv/x6";
import { useResizeObserver } from "@vueuse/core";
import createComponent from "./component";
import bindingEvent from "./bindingEvent";
import installStencil from "./stencil";
import { GRAPH_CONFIG } from "../default";
import type { Options } from "@antv/x6/lib/graph/options";

export interface IFlowGraphContext {
	// 拖拽面板
	stencil?: Addon.Stencil;
	// x6 graph实例
	graph?: Graph;
	// 当前点击的图形
	activeCell?: Ref<Cell>;
	// 当前点击的图形的配置
	activePanel: Ref<string>;
}
export interface IFlowGraphOptions {
	manual?: boolean;
	autoResize?: boolean;
}
export interface IReturnGraphFactory {
	configPanel?: Component;
}

type FactoryMapValue = (
	context: Required<Omit<IFlowGraphContext, "activePanel" | "activeCell">> & {
		appendStencil: (nodes: (Node | Node.Metadata)[]) => void;
	}
) => IReturnGraphFactory | void;

export const factoryMap = new Map<string, FactoryMapValue>();

/**
 * 自定义节点
 */
export function install(name: string, factory: FactoryMapValue) {
	if (factoryMap.has(name)) return console.warn(`${name}重复`);
	factoryMap.set(name, factory);
}

/**
 * 创建流程图
 * @param options
 * @returns
 */
export function create(options?: IFlowGraphOptions) {
	const mergeOptions = Object.assign(options || {}, { manual: false, autoResize: true });

	const configMap = new Map<string, IReturnGraphFactory>();

	// 当前激活的配置菜单
	const activePanel = ref("");

	const context: IFlowGraphContext = { activePanel };

	const { container, wrapEl, GraphComponent, FlowGraphProvide } = createComponent(context);
	const { createStencil, StencilComponent, appendStencil, allNodes } = installStencil(
		context as Required<IFlowGraphContext>
	);

	// 是否挂载(初始化)过
	let isMount = false;

	/**
	 * 初始化图形，在mount执行此方法
	 * @param options
	 * @returns
	 */
	const initGraph = (options?: Options.Manual) => {
		if (isMount) return context.graph;
		if (!container.value) throw new Error("没有container元素");
		const graph = new Graph({ container: container.value, ...GRAPH_CONFIG, ...(options || {}) });
		context.graph = markRaw(graph);
		isMount = true;
		// 绑定相关事件
		bindingEvent(context as Required<IFlowGraphContext>);
		// 创建拖拽的面板
		const stencil = createStencil(graph);
		if (stencil) {
			for (const [key, factory] of factoryMap) {
				const res = factory({ graph, stencil, appendStencil });
				res && configMap.set(key, res);
			}
		}
		return graph;
	};

	mergeOptions.manual || onMounted(initGraph);

	// 自动缩放图形;
	mergeOptions.autoResize &&
		onMounted(() => {
			useResizeObserver(wrapEl, (entries) => {
				if (!context.graph) return;
				const entry = entries[0];
				const { width, height } = entry.contentRect;
				context.graph.resize(width, height);
			});
		});

	onBeforeUnmount(() => {
		context.graph && context.graph.dispose();
		context.stencil && context.stencil.dispose();
		isMount = false;
		configMap.clear();
		allNodes.length = 0;
	});

	return {
		context,
		initGraph,
		GraphComponent,
		StencilComponent,
		FlowGraphProvide,
		ConfigPanel: () => {
			const Panel = configMap.get(activePanel.value);
			return Panel && Panel.configPanel ? h(Panel.configPanel, { context } as any) : null;
		}
	};
}
